/*
//@HEADER
// ************************************************************************
//
//                        Kokkos v. 2.0
//              Copyright (2014) Sandia Corporation
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the Corporation nor the names of the
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
//
// ************************************************************************
//@HEADER
*/

#ifndef KOKKOS_VIEW_HPP
#define KOKKOS_VIEW_HPP

#include <type_traits>
#include <string>
#include <algorithm>
#include <initializer_list>

#include <Kokkos_Core_fwd.hpp>
#include <Kokkos_HostSpace.hpp>
#include <Kokkos_MemoryTraits.hpp>
#include <Kokkos_ExecPolicy.hpp>

#if defined(KOKKOS_ENABLE_PROFILING)
#include <impl/Kokkos_Profiling_Interface.hpp>
#endif

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

namespace Kokkos {
namespace Impl {

template< class DataType >
struct ViewArrayAnalysis ;

template< class DataType , class ArrayLayout
        , typename ValueType =
          typename ViewArrayAnalysis< DataType >::non_const_value_type
        >
struct ViewDataAnalysis ;

template< class , class ... >
class ViewMapping {
  public:
  enum { is_assignable_data_type = false };
  enum { is_assignable = false };
};



template <typename IntType>
KOKKOS_INLINE_FUNCTION
std::size_t count_valid_integers(const IntType i0,
                            const IntType i1,
                            const IntType i2,
                            const IntType i3,
                            const IntType i4,
                            const IntType i5,
                            const IntType i6,
                            const IntType i7 ){
  static_assert(std::is_integral<IntType>::value, "count_valid_integers() must have integer arguments.");

  return ( i0 !=KOKKOS_INVALID_INDEX ) + ( i1 !=KOKKOS_INVALID_INDEX ) + ( i2 !=KOKKOS_INVALID_INDEX ) +
      ( i3 !=KOKKOS_INVALID_INDEX ) + ( i4 !=KOKKOS_INVALID_INDEX ) + ( i5 !=KOKKOS_INVALID_INDEX ) +
      ( i6 !=KOKKOS_INVALID_INDEX ) + ( i7 !=KOKKOS_INVALID_INDEX );


}

#ifndef KOKKOS_ENABLE_DEPRECATED_CODE
KOKKOS_INLINE_FUNCTION
void runtime_check_rank_device(const size_t dyn_rank,
                        const bool is_void_spec,
                        const size_t i0,
                        const size_t i1,
                        const size_t i2,
                        const size_t i3,
                        const size_t i4,
                        const size_t i5,
                        const size_t i6,
                        const size_t i7 ){

  if ( is_void_spec ) {
    const size_t num_passed_args = count_valid_integers(i0, i1, i2, i3,
        i4, i5, i6, i7);

    if ( num_passed_args != dyn_rank && is_void_spec ) {

      Kokkos::abort("Number of arguments passed to Kokkos::View() constructor must match the dynamic rank of the view.") ;

    }
  }
}
#else
KOKKOS_INLINE_FUNCTION
void runtime_check_rank_device(const size_t ,
                        const bool ,
                        const size_t ,
                        const size_t ,
                        const size_t ,
                        const size_t ,
                        const size_t ,
                        const size_t ,
                        const size_t ,
                        const size_t  ){

}
#endif

#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
#ifndef KOKKOS_ENABLE_DEPRECATED_CODE
KOKKOS_INLINE_FUNCTION
void runtime_check_rank_host(const size_t dyn_rank,
                        const bool is_void_spec,
                        const size_t i0,
                        const size_t i1,
                        const size_t i2,
                        const size_t i3,
                        const size_t i4,
                        const size_t i5,
                        const size_t i6,
                        const size_t i7, const std::string & label ){


  if ( is_void_spec ) {
    const size_t num_passed_args = count_valid_integers(i0, i1, i2, i3,
        i4, i5, i6, i7);

    if ( num_passed_args != dyn_rank ) {

      const std::string message = "Constructor for Kokkos View '" + label + "' has mismatched number of arguments. Number of arguments = "
        + std::to_string(num_passed_args) + " but dynamic rank = " + std::to_string(dyn_rank) + " \n";
      Kokkos::abort(message.c_str()) ;
    }
  }
}
#else
KOKKOS_INLINE_FUNCTION
void runtime_check_rank_host(const size_t ,
                        const bool ,
                        const size_t ,
                        const size_t ,
                        const size_t ,
                        const size_t ,
                        const size_t ,
                        const size_t ,
                        const size_t ,
                        const size_t , const std::string &){}
#endif
#endif

} /* namespace Impl */
} /* namespace Kokkos */

// Class to provide a uniform type
namespace Kokkos {
namespace Impl {
  template< class ViewType , int Traits = 0 >
  struct ViewUniformType;
}
}

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

namespace Kokkos {

/** \class ViewTraits
 *  \brief Traits class for accessing attributes of a View.
 *
 * This is an implementation detail of View.  It is only of interest
 * to developers implementing a new specialization of View.
 *
 * Template argument options:
 *   - View< DataType >
 *   - View< DataType , Space >
 *   - View< DataType , Space , MemoryTraits >
 *   - View< DataType , ArrayLayout >
 *   - View< DataType , ArrayLayout , Space >
 *   - View< DataType , ArrayLayout , MemoryTraits >
 *   - View< DataType , ArrayLayout , Space , MemoryTraits >
 *   - View< DataType , MemoryTraits >
 */

template< class DataType , class ... Properties >
struct ViewTraits ;

template<>
struct ViewTraits< void >
{
  typedef void  execution_space ;
  typedef void  memory_space ;
  typedef void  HostMirrorSpace ;
  typedef void  array_layout ;
  typedef void  memory_traits ;
  typedef void  specialize ;
};

template< class ... Prop >
struct ViewTraits< void , void , Prop ... >
{
  // Ignore an extraneous 'void'
  typedef typename ViewTraits<void,Prop...>::execution_space  execution_space ;
  typedef typename ViewTraits<void,Prop...>::memory_space     memory_space ;
  typedef typename ViewTraits<void,Prop...>::HostMirrorSpace  HostMirrorSpace ;
  typedef typename ViewTraits<void,Prop...>::array_layout     array_layout ;
  typedef typename ViewTraits<void,Prop...>::memory_traits    memory_traits ;
  typedef typename ViewTraits<void,Prop...>::specialize       specialize ;
};

template< class ArrayLayout , class ... Prop >
struct ViewTraits< typename std::enable_if< Kokkos::Impl::is_array_layout<ArrayLayout>::value >::type , ArrayLayout , Prop ... >
{
  // Specify layout, keep subsequent space and memory traits arguments

  typedef typename ViewTraits<void,Prop...>::execution_space  execution_space ;
  typedef typename ViewTraits<void,Prop...>::memory_space     memory_space ;
  typedef typename ViewTraits<void,Prop...>::HostMirrorSpace  HostMirrorSpace ;
  typedef          ArrayLayout                                array_layout ;
  typedef typename ViewTraits<void,Prop...>::memory_traits    memory_traits ;
  typedef typename ViewTraits<void,Prop...>::specialize       specialize ;
};

template< class Space , class ... Prop >
struct ViewTraits< typename std::enable_if< Kokkos::Impl::is_space<Space>::value >::type , Space , Prop ... >
{
  // Specify Space, memory traits should be the only subsequent argument.

  static_assert( std::is_same< typename ViewTraits<void,Prop...>::execution_space , void >::value &&
                 std::is_same< typename ViewTraits<void,Prop...>::memory_space    , void >::value &&
                 std::is_same< typename ViewTraits<void,Prop...>::HostMirrorSpace , void >::value &&
                 std::is_same< typename ViewTraits<void,Prop...>::array_layout    , void >::value
               , "Only one View Execution or Memory Space template argument" );

  typedef typename Space::execution_space                   execution_space ;
  typedef typename Space::memory_space                      memory_space ;
  typedef typename Kokkos::Impl::HostMirror< Space >::Space HostMirrorSpace ;
  typedef typename execution_space::array_layout            array_layout ;
  typedef typename ViewTraits<void,Prop...>::memory_traits  memory_traits ;
  typedef typename ViewTraits<void,Prop...>::specialize       specialize ;
};

template< class MemoryTraits , class ... Prop >
struct ViewTraits< typename std::enable_if< Kokkos::Impl::is_memory_traits<MemoryTraits>::value >::type , MemoryTraits , Prop ... >
{
  // Specify memory trait, should not be any subsequent arguments

  static_assert( std::is_same< typename ViewTraits<void,Prop...>::execution_space , void >::value &&
                 std::is_same< typename ViewTraits<void,Prop...>::memory_space    , void >::value &&
                 std::is_same< typename ViewTraits<void,Prop...>::array_layout    , void >::value &&
                 std::is_same< typename ViewTraits<void,Prop...>::memory_traits   , void >::value
               , "MemoryTrait is the final optional template argument for a View" );

  typedef void          execution_space ;
  typedef void          memory_space ;
  typedef void          HostMirrorSpace ;
  typedef void          array_layout ;
  typedef MemoryTraits  memory_traits ;
  typedef void          specialize ;
};


template< class DataType , class ... Properties >
struct ViewTraits {
private:

  // Unpack the properties arguments
  typedef ViewTraits< void , Properties ... >  prop ;

  typedef typename
    std::conditional< ! std::is_same< typename prop::execution_space , void >::value
                    , typename prop::execution_space
                    , Kokkos::DefaultExecutionSpace
                    >::type
      ExecutionSpace ;

  typedef typename
    std::conditional< ! std::is_same< typename prop::memory_space , void >::value
                    , typename prop::memory_space
                    , typename ExecutionSpace::memory_space
                    >::type
      MemorySpace ;

  typedef typename
    std::conditional< ! std::is_same< typename prop::array_layout , void >::value
                    , typename prop::array_layout
                    , typename ExecutionSpace::array_layout
                    >::type
      ArrayLayout ;

  typedef typename
    std::conditional
      < ! std::is_same< typename prop::HostMirrorSpace , void >::value
      , typename prop::HostMirrorSpace
      , typename Kokkos::Impl::HostMirror< ExecutionSpace >::Space
      >::type
      HostMirrorSpace ;

  typedef typename
    std::conditional< ! std::is_same< typename prop::memory_traits , void >::value
                    , typename prop::memory_traits
                    , typename Kokkos::MemoryManaged
                    >::type
      MemoryTraits ;

  // Analyze data type's properties,
  // May be specialized based upon the layout and value type
  typedef Kokkos::Impl::ViewDataAnalysis< DataType , ArrayLayout > data_analysis ;

public:

  //------------------------------------
  // Data type traits:

  typedef typename data_analysis::type            data_type ;
  typedef typename data_analysis::const_type      const_data_type ;
  typedef typename data_analysis::non_const_type  non_const_data_type ;

  //------------------------------------
  // Compatible array of trivial type traits:

  typedef typename data_analysis::scalar_array_type            scalar_array_type ;
  typedef typename data_analysis::const_scalar_array_type      const_scalar_array_type ;
  typedef typename data_analysis::non_const_scalar_array_type  non_const_scalar_array_type ;

  //------------------------------------
  // Value type traits:

  typedef typename data_analysis::value_type            value_type ;
  typedef typename data_analysis::const_value_type      const_value_type ;
  typedef typename data_analysis::non_const_value_type  non_const_value_type ;

  //------------------------------------
  // Mapping traits:

  typedef ArrayLayout                         array_layout ;
  typedef typename data_analysis::dimension   dimension ;

  typedef typename std::conditional<
                      std::is_same<typename data_analysis::specialize,void>::value
                      ,typename prop::specialize
                      ,typename data_analysis::specialize>::type
                   specialize ; /* mapping specialization tag */

  enum { rank         = dimension::rank };
  enum { rank_dynamic = dimension::rank_dynamic };

  //------------------------------------
  // Execution space, memory space, memory access traits, and host mirror space.

  typedef ExecutionSpace                              execution_space ;
  typedef MemorySpace                                 memory_space ;
  typedef Kokkos::Device<ExecutionSpace,MemorySpace>  device_type ;
  typedef MemoryTraits                                memory_traits ;
  typedef HostMirrorSpace                             host_mirror_space ;

  typedef typename MemorySpace::size_type  size_type ;

  enum { is_hostspace      = std::is_same< MemorySpace , HostSpace >::value };
  enum { is_managed        = MemoryTraits::is_unmanaged    == 0 };
  enum { is_random_access  = MemoryTraits::is_random_access == 1 };

  //------------------------------------
};

/** \class View
 *  \brief View to an array of data.
 *
 * A View represents an array of one or more dimensions.
 * For details, please refer to Kokkos' tutorial materials.
 *
 * \section Kokkos_View_TemplateParameters Template parameters
 *
 * This class has both required and optional template parameters.  The
 * \c DataType parameter must always be provided, and must always be
 * first. The parameters \c Arg1Type, \c Arg2Type, and \c Arg3Type are
 * placeholders for different template parameters.  The default value
 * of the fifth template parameter \c Specialize suffices for most use
 * cases.  When explaining the template parameters, we won't refer to
 * \c Arg1Type, \c Arg2Type, and \c Arg3Type; instead, we will refer
 * to the valid categories of template parameters, in whatever order
 * they may occur.
 *
 * Valid ways in which template arguments may be specified:
 *   - View< DataType >
 *   - View< DataType , Layout >
 *   - View< DataType , Layout , Space >
 *   - View< DataType , Layout , Space , MemoryTraits >
 *   - View< DataType , Space >
 *   - View< DataType , Space , MemoryTraits >
 *   - View< DataType , MemoryTraits >
 *
 * \tparam DataType (required) This indicates both the type of each
 *   entry of the array, and the combination of compile-time and
 *   run-time array dimension(s).  For example, <tt>double*</tt>
 *   indicates a one-dimensional array of \c double with run-time
 *   dimension, and <tt>int*[3]</tt> a two-dimensional array of \c int
 *   with run-time first dimension and compile-time second dimension
 *   (of 3).  In general, the run-time dimensions (if any) must go
 *   first, followed by zero or more compile-time dimensions.  For
 *   more examples, please refer to the tutorial materials.
 *
 * \tparam Space (required) The memory space.
 *
 * \tparam Layout (optional) The array's layout in memory.  For
 *   example, LayoutLeft indicates a column-major (Fortran style)
 *   layout, and LayoutRight a row-major (C style) layout.  If not
 *   specified, this defaults to the preferred layout for the
 *   <tt>Space</tt>.
 *
 * \tparam MemoryTraits (optional) Assertion of the user's intended
 *   access behavior.  For example, RandomAccess indicates read-only
 *   access with limited spatial locality, and Unmanaged lets users
 *   wrap externally allocated memory in a View without automatic
 *   deallocation.
 *
 * \section Kokkos_View_MT MemoryTraits discussion
 *
 * \subsection Kokkos_View_MT_Interp MemoryTraits interpretation depends on Space
 *
 * Some \c MemoryTraits options may have different interpretations for
 * different \c Space types.  For example, with the Cuda device,
 * \c RandomAccess tells Kokkos to fetch the data through the texture
 * cache, whereas the non-GPU devices have no such hardware construct.
 *
 * \subsection Kokkos_View_MT_PrefUse Preferred use of MemoryTraits
 *
 * Users should defer applying the optional \c MemoryTraits parameter
 * until the point at which they actually plan to rely on it in a
 * computational kernel.  This minimizes the number of template
 * parameters exposed in their code, which reduces the cost of
 * compilation.  Users may always assign a View without specified
 * \c MemoryTraits to a compatible View with that specification.
 * For example:
 * \code
 * // Pass in the simplest types of View possible.
 * void
 * doSomething (View<double*, Cuda> out,
 *              View<const double*, Cuda> in)
 * {
 *   // Assign the "generic" View in to a RandomAccess View in_rr.
 *   // Note that RandomAccess View objects must have const data.
 *   View<const double*, Cuda, RandomAccess> in_rr = in;
 *   // ... do something with in_rr and out ...
 * }
 * \endcode
 */
template< class DataType , class ... Properties >
class View ;

} /* namespace Kokkos */

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

#include <impl/Kokkos_ViewMapping.hpp>
#include <impl/Kokkos_ViewArray.hpp>

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

namespace Kokkos {

namespace {

constexpr Kokkos::Impl::ALL_t
  ALL = Kokkos::Impl::ALL_t();

constexpr Kokkos::Impl::WithoutInitializing_t
  WithoutInitializing = Kokkos::Impl::WithoutInitializing_t();

constexpr Kokkos::Impl::AllowPadding_t
  AllowPadding        = Kokkos::Impl::AllowPadding_t();

}

/** \brief  Create View allocation parameter bundle from argument list.
 *
 *  Valid argument list members are:
 *    1) label as a "string" or std::string
 *    2) memory space instance of the View::memory_space type
 *    3) execution space instance compatible with the View::memory_space
 *    4) Kokkos::WithoutInitializing to bypass initialization
 *    4) Kokkos::AllowPadding to allow allocation to pad dimensions for memory alignment
 */
template< class ... Args >
inline
Impl::ViewCtorProp< typename Impl::ViewCtorProp< void , Args >::type ... >
view_alloc( Args const & ... args )
{
  typedef
    Impl::ViewCtorProp< typename Impl::ViewCtorProp< void , Args >::type ... >
      return_type ;

  static_assert( ! return_type::has_pointer
               , "Cannot give pointer-to-memory for view allocation" );

  return return_type( args... );
}

template< class ... Args >
KOKKOS_INLINE_FUNCTION
Impl::ViewCtorProp< typename Impl::ViewCtorProp< void , Args >::type ... >
view_wrap( Args const & ... args )
{
  typedef
    Impl::ViewCtorProp< typename Impl::ViewCtorProp< void , Args >::type ... >
      return_type ;

  static_assert( ! return_type::has_memory_space &&
                 ! return_type::has_execution_space &&
                 ! return_type::has_label &&
                 return_type::has_pointer
               , "Must only give pointer-to-memory for view wrapping" );

  return return_type( args... );
}

} /* namespace Kokkos */

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

namespace Kokkos {

template< class DataType , class ... Properties >
class View ;

template< class > struct is_view : public std::false_type {};

template< class D, class ... P >
struct is_view< View<D,P...> > : public std::true_type {};

template< class D, class ... P >
struct is_view< const View<D,P...> > : public std::true_type {};

template< class DataType , class ... Properties >
class View : public ViewTraits< DataType , Properties ... > {
private:

  template< class , class ... > friend class View ;
  template< class , class ... > friend class Kokkos::Impl::ViewMapping ;

public:

  typedef ViewTraits< DataType , Properties ... > traits ;

private:

  typedef Kokkos::Impl::ViewMapping< traits , typename traits::specialize > map_type ;
  typedef Kokkos::Impl::SharedAllocationTracker      track_type ;

  track_type  m_track ;
  map_type    m_map ;

public:

  //----------------------------------------
  /** \brief  Compatible view of array of scalar types */
  typedef View< typename traits::scalar_array_type ,
                typename traits::array_layout ,
                typename traits::device_type ,
                typename traits::memory_traits >
    array_type ;

  /** \brief  Compatible view of const data type */
  typedef View< typename traits::const_data_type ,
                typename traits::array_layout ,
                typename traits::device_type ,
                typename traits::memory_traits >
    const_type ;

  /** \brief  Compatible view of non-const data type */
  typedef View< typename traits::non_const_data_type ,
                typename traits::array_layout ,
                typename traits::device_type ,
                typename traits::memory_traits >
    non_const_type ;

  /** \brief  Compatible HostMirror view */
  typedef View< typename traits::non_const_data_type ,
                typename traits::array_layout ,
                typename traits::host_mirror_space >
    HostMirror ;

  /** \brief  Compatible HostMirror view */
  typedef View< typename traits::non_const_data_type ,
                typename traits::array_layout ,
                typename traits::host_mirror_space >
    host_mirror_type ;

  /** \brief Unified types */
  typedef typename Impl::ViewUniformType<View,0>::type uniform_type;
  typedef typename Impl::ViewUniformType<View,0>::const_type uniform_const_type;
  typedef typename Impl::ViewUniformType<View,0>::runtime_type uniform_runtime_type;
  typedef typename Impl::ViewUniformType<View,0>::runtime_const_type uniform_runtime_const_type;
  typedef typename Impl::ViewUniformType<View,0>::nomemspace_type uniform_nomemspace_type;
  typedef typename Impl::ViewUniformType<View,0>::const_nomemspace_type uniform_const_nomemspace_type;
  typedef typename Impl::ViewUniformType<View,0>::runtime_nomemspace_type uniform_runtime_nomemspace_type;
  typedef typename Impl::ViewUniformType<View,0>::runtime_const_nomemspace_type uniform_runtime_const_nomemspace_type;

  //----------------------------------------
  // Domain rank and extents

  enum { Rank = map_type::Rank };

 /** \brief rank() to be implemented
  */
  //KOKKOS_INLINE_FUNCTION
  //static
  //constexpr unsigned rank() { return map_type::Rank; }

  template< typename iType >
  KOKKOS_INLINE_FUNCTION constexpr
  typename std::enable_if< std::is_integral<iType>::value , size_t >::type
  extent( const iType & r ) const noexcept
    { return m_map.extent(r); }

  static KOKKOS_INLINE_FUNCTION constexpr
  size_t
  static_extent( const unsigned r ) noexcept
    { return map_type::static_extent(r); }

  template< typename iType >
  KOKKOS_INLINE_FUNCTION constexpr
  typename std::enable_if< std::is_integral<iType>::value , int >::type
  extent_int( const iType & r ) const noexcept
    { return static_cast<int>(m_map.extent(r)); }

  KOKKOS_INLINE_FUNCTION constexpr
  typename traits::array_layout layout() const
    { return m_map.layout(); }

  //----------------------------------------
  /*  Deprecate all 'dimension' functions in favor of
   *  ISO/C++ vocabulary 'extent'.
   */

#ifdef KOKKOS_ENABLE_DEPRECATED_CODE

  template< typename iType >
  KOKKOS_INLINE_FUNCTION constexpr
  typename std::enable_if< std::is_integral<iType>::value , size_t >::type
  dimension( const iType & r ) const { return extent( r ); }

  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_0() const { return m_map.dimension_0(); }
  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_1() const { return m_map.dimension_1(); }
  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_2() const { return m_map.dimension_2(); }
  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_3() const { return m_map.dimension_3(); }
  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_4() const { return m_map.dimension_4(); }
  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_5() const { return m_map.dimension_5(); }
  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_6() const { return m_map.dimension_6(); }
  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_7() const { return m_map.dimension_7(); }

#endif

  //----------------------------------------

  KOKKOS_INLINE_FUNCTION constexpr size_t size() const { return m_map.dimension_0() *
                                                                m_map.dimension_1() *
                                                                m_map.dimension_2() *
                                                                m_map.dimension_3() *
                                                                m_map.dimension_4() *
                                                                m_map.dimension_5() *
                                                                m_map.dimension_6() *
                                                                m_map.dimension_7(); }

  KOKKOS_INLINE_FUNCTION constexpr size_t stride_0() const { return m_map.stride_0(); }
  KOKKOS_INLINE_FUNCTION constexpr size_t stride_1() const { return m_map.stride_1(); }
  KOKKOS_INLINE_FUNCTION constexpr size_t stride_2() const { return m_map.stride_2(); }
  KOKKOS_INLINE_FUNCTION constexpr size_t stride_3() const { return m_map.stride_3(); }
  KOKKOS_INLINE_FUNCTION constexpr size_t stride_4() const { return m_map.stride_4(); }
  KOKKOS_INLINE_FUNCTION constexpr size_t stride_5() const { return m_map.stride_5(); }
  KOKKOS_INLINE_FUNCTION constexpr size_t stride_6() const { return m_map.stride_6(); }
  KOKKOS_INLINE_FUNCTION constexpr size_t stride_7() const { return m_map.stride_7(); }

  template< typename iType >
  KOKKOS_INLINE_FUNCTION constexpr
  typename std::enable_if< std::is_integral<iType>::value , size_t >::type
  stride(iType r) const {
    return (r == 0 ? m_map.stride_0() :
           (r == 1 ? m_map.stride_1() :
           (r == 2 ? m_map.stride_2() :
           (r == 3 ? m_map.stride_3() :
           (r == 4 ? m_map.stride_4() :
           (r == 5 ? m_map.stride_5() :
           (r == 6 ? m_map.stride_6() :
                     m_map.stride_7())))))));
  }

  template< typename iType >
  KOKKOS_INLINE_FUNCTION void stride( iType * const s ) const { m_map.stride(s); }

  //----------------------------------------
  // Range span is the span which contains all members.

  typedef typename map_type::reference_type  reference_type ;
  typedef typename map_type::pointer_type    pointer_type ;

  enum { reference_type_is_lvalue_reference = std::is_lvalue_reference< reference_type >::value };

  KOKKOS_INLINE_FUNCTION constexpr size_t span() const { return m_map.span(); }
#ifdef KOKKOS_ENABLE_DEPRECATED_CODE
  // Deprecated, use 'span()' instead
  KOKKOS_INLINE_FUNCTION constexpr size_t capacity() const { return m_map.span(); }
#endif
  KOKKOS_INLINE_FUNCTION bool span_is_contiguous() const { return m_map.span_is_contiguous(); }
  KOKKOS_INLINE_FUNCTION constexpr pointer_type data() const { return m_map.data(); }

#ifdef KOKKOS_ENABLE_DEPRECATED_CODE
  // Deprecated, use 'span_is_contigous()' instead
  KOKKOS_INLINE_FUNCTION constexpr bool   is_contiguous() const { return m_map.span_is_contiguous(); }
  // Deprecated, use 'data()' instead
  KOKKOS_INLINE_FUNCTION constexpr pointer_type ptr_on_device() const { return m_map.data(); }
#endif

  //----------------------------------------
  // Allow specializations to query their specialized map

#ifdef KOKKOS_ENABLE_DEPRECATED_CODE
  KOKKOS_INLINE_FUNCTION
  const Kokkos::Impl::ViewMapping< traits , typename traits::specialize > &
  implementation_map() const { return m_map ; }
#endif
  KOKKOS_INLINE_FUNCTION
  const Kokkos::Impl::ViewMapping< traits , typename traits::specialize > &
  impl_map() const { return m_map ; }
  KOKKOS_INLINE_FUNCTION
  const Kokkos::Impl::SharedAllocationTracker &
  impl_track() const { return m_track ; }
  //----------------------------------------

private:

  enum {
    is_layout_left = std::is_same< typename traits::array_layout
                                  , Kokkos::LayoutLeft >::value ,

    is_layout_right = std::is_same< typename traits::array_layout
                                  , Kokkos::LayoutRight >::value ,

    is_layout_stride = std::is_same< typename traits::array_layout
                                   , Kokkos::LayoutStride >::value ,

    is_default_map =
      std::is_same< typename traits::specialize , void >::value &&
      ( is_layout_left || is_layout_right || is_layout_stride )
  };

  template< class Space , bool = Kokkos::Impl::MemorySpaceAccess< Space , typename traits::memory_space >::accessible > struct verify_space
    { KOKKOS_FORCEINLINE_FUNCTION static void check() {} };

  template< class Space > struct verify_space<Space,false>
    { KOKKOS_FORCEINLINE_FUNCTION static void check()
        { Kokkos::abort("Kokkos::View ERROR: attempt to access inaccessible memory space"); };
    };

#if defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )

#define KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( ARG ) \
  View::template verify_space< Kokkos::Impl::ActiveExecutionMemorySpace >::check(); \
  Kokkos::Impl::view_verify_operator_bounds< typename traits::memory_space > ARG ;

#else

#define KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( ARG ) \
  View::template verify_space< Kokkos::Impl::ActiveExecutionMemorySpace >::check();

#endif

public:
#ifdef KOKKOS_ENABLE_DEPRECATED_CODE
   template< class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<( Kokkos::Impl::are_integral<Args...>::value
                             && ( 0 == Rank )
                           ), reference_type >::type
   operator()( Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,args...) )
       return m_map.reference();
     }

   template< typename I0
              , class ... Args>
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,Args...>::value
       && ( 1 == Rank )
       && ! is_default_map
     ), reference_type >::type
   operator()( const I0 & i0,
               Args ... args) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,args...) )
       return m_map.reference(i0);
     }

   template< typename I0
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,Args...>::value
       && ( 1 == Rank )
       && is_default_map
       && ! is_layout_stride
     ), reference_type >::type
   operator()( const I0 & i0
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,args...) )
       return m_map.m_impl_handle[ i0 ];
     }

   template< typename I0
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,Args...>::value
       && ( 1 == Rank )
       && is_default_map
       && is_layout_stride
     ), reference_type >::type
   operator()( const I0 & i0
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,args...) )
       return m_map.m_impl_handle[ m_map.m_impl_offset.m_stride.S0 * i0 ];
     }

   //------------------------------
     // Rank 1 operator[]

     template< typename I0 >
     KOKKOS_FORCEINLINE_FUNCTION
     typename std::enable_if<
       ( Kokkos::Impl::are_integral<I0>::value
         && ( 1 == Rank )
         && ! is_default_map
       ), reference_type >::type
     operator[]( const I0 & i0 ) const
       {
         KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0) )
         return m_map.reference(i0);
       }

    template< typename I0 >
     KOKKOS_FORCEINLINE_FUNCTION
     typename std::enable_if<
       ( Kokkos::Impl::are_integral<I0>::value
         && ( 1 == Rank )
         && is_default_map
         && ! is_layout_stride
       ), reference_type >::type
     operator[]( const I0 & i0 ) const
       {
         KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0) )
         return m_map.m_impl_handle[ i0 ];
       }

     template< typename I0 >
     KOKKOS_FORCEINLINE_FUNCTION
     typename std::enable_if<
       ( Kokkos::Impl::are_integral<I0>::value
         && ( 1 == Rank )
         && is_default_map
         && is_layout_stride
       ), reference_type >::type
     operator[]( const I0 & i0 ) const
       {
         KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0) )
         return m_map.m_impl_handle[ m_map.m_impl_offset.m_stride.S0 * i0 ];
       }

   template< typename I0 , typename I1
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,Args...>::value
       && ( 2 == Rank )
       && ! is_default_map
     ), reference_type >::type
   operator()( const I0 & i0 , const I1 & i1
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,args...) )
       return m_map.reference(i0,i1);
     }

   template< typename I0 , typename I1
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,Args...>::value
       && ( 2 == Rank )
       && is_default_map
       && is_layout_left && ( traits::rank_dynamic == 0 )
     ), reference_type >::type
   operator()( const I0 & i0 , const I1 & i1
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,args...) )
       return m_map.m_impl_handle[ i0 + m_map.m_impl_offset.m_dim.N0 * i1 ];
     }

   template< typename I0 , typename I1
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,Args...>::value
       && ( 2 == Rank )
       && is_default_map
       && is_layout_left && ( traits::rank_dynamic != 0 )
     ), reference_type >::type
   operator()( const I0 & i0 , const I1 & i1
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,args...) )
       return m_map.m_impl_handle[ i0 + m_map.m_impl_offset.m_stride * i1 ];
     }

   template< typename I0 , typename I1
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,Args...>::value
       && ( 2 == Rank )
       && is_default_map
       && is_layout_right && ( traits::rank_dynamic == 0 )
     ), reference_type >::type
   operator()( const I0 & i0 , const I1 & i1
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,args...) )
       return m_map.m_impl_handle[ i1 + m_map.m_impl_offset.m_dim.N1 * i0 ];
     }

   template< typename I0 , typename I1
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,Args...>::value
       && ( 2 == Rank )
       && is_default_map
       && is_layout_right && ( traits::rank_dynamic != 0 )
     ), reference_type >::type
   operator()( const I0 & i0 , const I1 & i1
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,args...) )
       return m_map.m_impl_handle[ i1 + m_map.m_impl_offset.m_stride * i0 ];
     }

   template< typename I0 , typename I1
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,Args...>::value
       && ( 2 == Rank )
       && is_default_map
       && is_layout_stride
     ), reference_type >::type
   operator()( const I0 & i0 , const I1 & i1
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,args...) )
       return m_map.m_impl_handle[ i0 * m_map.m_impl_offset.m_stride.S0 +
                              i1 * m_map.m_impl_offset.m_stride.S1 ];
     }

   //------------------------------
   // Rank 3

   template< typename I0 , typename I1 , typename I2
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,Args...>::value
       && ( 3 == Rank )
       && is_default_map
     ), reference_type >::type
   operator()( const I0 & i0 , const I1 & i1 , const I2 & i2
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,args...) )
       return m_map.m_impl_handle[ m_map.m_impl_offset(i0,i1,i2) ];
     }

   template< typename I0 , typename I1 , typename I2
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,Args...>::value
       && ( 3 == Rank )
       && ! is_default_map
     ), reference_type >::type
   operator()( const I0 & i0 , const I1 & i1 , const I2 & i2
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,args...) )
       return m_map.reference(i0,i1,i2);
     }

   //------------------------------
   // Rank 4

 template< typename I0 , typename I1 , typename I2 , typename I3
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,I3,Args...>::value
       && ( 4 == Rank )
       && is_default_map
     ), reference_type >::type
   operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,args...) )
       return m_map.m_impl_handle[ m_map.m_impl_offset(i0,i1,i2,i3) ];
     }

   template< typename I0 , typename I1 , typename I2 , typename I3
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,I3,Args...>::value
       && ( 4 == Rank )
       && ! is_default_map
     ), reference_type >::type
   operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,args...) )
       return m_map.reference(i0,i1,i2,i3);
     }

   //------------------------------
   // Rank 5

   template< typename I0 , typename I1 , typename I2 , typename I3
           , typename I4
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,Args...>::value
       && ( 5 == Rank )
       && is_default_map
     ), reference_type >::type
   operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
             , const I4 & i4
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,args...) )
       return m_map.m_impl_handle[ m_map.m_impl_offset(i0,i1,i2,i3,i4) ];
     }

   template< typename I0 , typename I1 , typename I2 , typename I3
           , typename I4
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,Args...>::value
       && ( 5 == Rank )
       && ! is_default_map
     ), reference_type >::type
   operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
             , const I4 & i4
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,args...) )
       return m_map.reference(i0,i1,i2,i3,i4);
     }

   //------------------------------
   // Rank 6

   template< typename I0 , typename I1 , typename I2 , typename I3
           , typename I4 , typename I5
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,Args...>::value
       && ( 6 == Rank )
       && is_default_map
     ), reference_type >::type
   operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
             , const I4 & i4 , const I5 & i5
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,args...) )
       return m_map.m_impl_handle[ m_map.m_impl_offset(i0,i1,i2,i3,i4,i5) ];
     }

   template< typename I0 , typename I1 , typename I2 , typename I3
           , typename I4 , typename I5
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,Args...>::value
       && ( 6 == Rank )
       && ! is_default_map
     ), reference_type >::type
   operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
             , const I4 & i4 , const I5 & i5
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,args...) )
       return m_map.reference(i0,i1,i2,i3,i4,i5);
     }

   //------------------------------
   // Rank 7

   template< typename I0 , typename I1 , typename I2 , typename I3
           , typename I4 , typename I5 , typename I6
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,I6,Args...>::value
       && ( 7 == Rank )
       && is_default_map
     ), reference_type >::type
   operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
             , const I4 & i4 , const I5 & i5 , const I6 & i6
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,i6,args...) )
       return m_map.m_impl_handle[ m_map.m_impl_offset(i0,i1,i2,i3,i4,i5,i6) ];
     }

   template< typename I0 , typename I1 , typename I2 , typename I3
           , typename I4 , typename I5 , typename I6
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,I6,Args...>::value
       && ( 7 == Rank )
       && ! is_default_map
     ), reference_type >::type
   operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
             , const I4 & i4 , const I5 & i5 , const I6 & i6
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,i6,args...) )
       return m_map.reference(i0,i1,i2,i3,i4,i5,i6);
     }

   //------------------------------
   // Rank 8

   template< typename I0 , typename I1 , typename I2 , typename I3
           , typename I4 , typename I5 , typename I6 , typename I7
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,I6,I7,Args...>::value
       && ( 8 == Rank )
       && is_default_map
     ), reference_type >::type
   operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
             , const I4 & i4 , const I5 & i5 , const I6 & i6 , const I7 & i7
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,i6,i7,args...) )
       return m_map.m_impl_handle[ m_map.m_impl_offset(i0,i1,i2,i3,i4,i5,i6,i7) ];
     }

   template< typename I0 , typename I1 , typename I2 , typename I3
           , typename I4 , typename I5 , typename I6 , typename I7
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,I6,I7,Args...>::value
       && ( 8 == Rank )
       && ! is_default_map
     ), reference_type >::type
   operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
             , const I4 & i4 , const I5 & i5 , const I6 & i6 , const I7 & i7
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,i6,i7,args...) )
       return m_map.reference(i0,i1,i2,i3,i4,i5,i6,i7);
     }


  #else
  //------------------------------
  // Rank 0 operator()

 KOKKOS_FORCEINLINE_FUNCTION
  reference_type
  operator()() const
    {
      return m_map.reference();
    }
  //------------------------------
  // Rank 1 operator()


  template< typename I0>
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0>::value
      && ( 1 == Rank )
      && ! is_default_map
    ), reference_type >::type
  operator()( const I0 & i0) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0) )
      return m_map.reference(i0);
    }

  template< typename I0>
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0>::value
      && ( 1 == Rank )
      && is_default_map
      && ! is_layout_stride
    ), reference_type >::type
  operator()( const I0 & i0 ) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0) )
      return m_map.m_impl_handle[ i0 ];
    }

  template< typename I0 >
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0>::value
      && ( 1 == Rank )
      && is_default_map
      && is_layout_stride
    ), reference_type >::type
  operator()( const I0 & i0) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0) )
      return m_map.m_impl_handle[ m_map.m_impl_offset.m_stride.S0 * i0 ];
    }
  //------------------------------
    // Rank 1 operator[]

    template< typename I0 >
    KOKKOS_FORCEINLINE_FUNCTION
    typename std::enable_if<
      ( Kokkos::Impl::are_integral<I0>::value
        && ( 1 == Rank )
        && ! is_default_map
      ), reference_type >::type
    operator[]( const I0 & i0 ) const
      {
        KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0) )
        return m_map.reference(i0);
      }

    template< typename I0 >
    KOKKOS_FORCEINLINE_FUNCTION
    typename std::enable_if<
      ( Kokkos::Impl::are_integral<I0>::value
        && ( 1 == Rank )
        && is_default_map
        && ! is_layout_stride
      ), reference_type >::type
    operator[]( const I0 & i0 ) const
      {
        KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0) )
        return m_map.m_impl_handle[ i0 ];
      }

    template< typename I0 >
    KOKKOS_FORCEINLINE_FUNCTION
    typename std::enable_if<
      ( Kokkos::Impl::are_integral<I0>::value
        && ( 1 == Rank )
        && is_default_map
        && is_layout_stride
      ), reference_type >::type
    operator[]( const I0 & i0 ) const
      {
        KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0) )
        return m_map.m_impl_handle[ m_map.m_impl_offset.m_stride.S0 * i0 ];
      }


    //------------------------------
  // Rank 2

  template< typename I0 , typename I1 >
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0,I1>::value
      && ( 2 == Rank )
      && ! is_default_map
    ), reference_type >::type
  operator()( const I0 & i0 , const I1 & i1) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1) )
      return m_map.reference(i0,i1);
    }

  template< typename I0 , typename I1 >
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0,I1>::value
      && ( 2 == Rank )
      && is_default_map
      && is_layout_left && ( traits::rank_dynamic == 0 )
    ), reference_type >::type
  operator()( const I0 & i0 , const I1 & i1) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1) )
      return m_map.m_impl_handle[ i0 + m_map.m_impl_offset.m_dim.N0 * i1 ];
    }

  template< typename I0 , typename I1>
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0,I1>::value
      && ( 2 == Rank )
      && is_default_map
      && is_layout_left && ( traits::rank_dynamic != 0 )
    ), reference_type >::type
  operator()( const I0 & i0 , const I1 & i1) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1) )
      return m_map.m_impl_handle[ i0 + m_map.m_impl_offset.m_stride * i1 ];
    }

  template< typename I0 , typename I1 >
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0,I1>::value
      && ( 2 == Rank )
      && is_default_map
      && is_layout_right && ( traits::rank_dynamic == 0 )
    ), reference_type >::type
  operator()( const I0 & i0 , const I1 & i1 ) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1) )
      return m_map.m_impl_handle[ i1 + m_map.m_impl_offset.m_dim.N1 * i0 ];
    }

  template< typename I0 , typename I1 >
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0,I1>::value
      && ( 2 == Rank )
      && is_default_map
      && is_layout_right && ( traits::rank_dynamic != 0 )
    ), reference_type >::type
  operator()( const I0 & i0 , const I1 & i1 ) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1) )
      return m_map.m_impl_handle[ i1 + m_map.m_impl_offset.m_stride * i0 ];
    }

  template< typename I0 , typename I1>
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0,I1>::value
      && ( 2 == Rank )
      && is_default_map
      && is_layout_stride
    ), reference_type >::type
  operator()( const I0 & i0 , const I1 & i1 ) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1) )
      return m_map.m_impl_handle[ i0 * m_map.m_impl_offset.m_stride.S0 +
                             i1 * m_map.m_impl_offset.m_stride.S1 ];
    }

  //------------------------------
  // Rank 3

  template< typename I0 , typename I1 , typename I2 >
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0,I1,I2>::value
      && ( 3 == Rank )
      && is_default_map
    ), reference_type >::type
  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2) )
      return m_map.m_impl_handle[ m_map.m_impl_offset(i0,i1,i2) ];
    }

  template< typename I0 , typename I1 , typename I2>
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0,I1,I2>::value
      && ( 3 == Rank )
      && ! is_default_map
    ), reference_type >::type
  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2) )
      return m_map.reference(i0,i1,i2);
    }

  //------------------------------
  // Rank 4

  template< typename I0 , typename I1 , typename I2 , typename I3>
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0,I1,I2,I3>::value
      && ( 4 == Rank )
      && is_default_map
    ), reference_type >::type
  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3) )
      return m_map.m_impl_handle[ m_map.m_impl_offset(i0,i1,i2,i3) ];
    }

  template< typename I0 , typename I1 , typename I2 , typename I3 >
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0,I1,I2,I3>::value
      && ( 4 == Rank )
      && ! is_default_map
    ), reference_type >::type
  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3) )
      return m_map.reference(i0,i1,i2,i3);
    }

  //------------------------------
  // Rank 5

  template< typename I0 , typename I1 , typename I2 , typename I3
          , typename I4>
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4>::value
      && ( 5 == Rank )
      && is_default_map
    ), reference_type >::type
  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
            , const I4 & i4 ) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4) )
      return m_map.m_impl_handle[ m_map.m_impl_offset(i0,i1,i2,i3,i4) ];
    }

  template< typename I0 , typename I1 , typename I2 , typename I3
          , typename I4>
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4>::value
      && ( 5 == Rank )
      && ! is_default_map
    ), reference_type >::type
  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
            , const I4 & i4) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4) )
      return m_map.reference(i0,i1,i2,i3,i4);
    }

  //------------------------------
  // Rank 6

  template< typename I0 , typename I1 , typename I2 , typename I3
          , typename I4 , typename I5 >
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5>::value
      && ( 6 == Rank )
      && is_default_map
    ), reference_type >::type
  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
            , const I4 & i4 , const I5 & i5 ) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5) )
      return m_map.m_impl_handle[ m_map.m_impl_offset(i0,i1,i2,i3,i4,i5) ];
    }

  template< typename I0 , typename I1 , typename I2 , typename I3
          , typename I4 , typename I5>
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5>::value
      && ( 6 == Rank )
      && ! is_default_map
    ), reference_type >::type
  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
            , const I4 & i4 , const I5 & i5) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5) )
      return m_map.reference(i0,i1,i2,i3,i4,i5);
    }

  //------------------------------
  // Rank 7

  template< typename I0 , typename I1 , typename I2 , typename I3
          , typename I4 , typename I5 , typename I6>
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,I6>::value
      && ( 7 == Rank )
      && is_default_map
    ), reference_type >::type
  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
            , const I4 & i4 , const I5 & i5 , const I6 & i6) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,i6) )
      return m_map.m_impl_handle[ m_map.m_impl_offset(i0,i1,i2,i3,i4,i5,i6) ];
    }

  template< typename I0 , typename I1 , typename I2 , typename I3
          , typename I4 , typename I5 , typename I6 >
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,I6>::value
      && ( 7 == Rank )
      && ! is_default_map
    ), reference_type >::type
  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
            , const I4 & i4 , const I5 & i5 , const I6 & i6) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,i6) )
      return m_map.reference(i0,i1,i2,i3,i4,i5,i6);
    }

  //------------------------------
  // Rank 8

  template< typename I0 , typename I1 , typename I2 , typename I3
          , typename I4 , typename I5 , typename I6 , typename I7 >
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,I6,I7>::value
      && ( 8 == Rank )
      && is_default_map
    ), reference_type >::type
  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
            , const I4 & i4 , const I5 & i5 , const I6 & i6 , const I7 & i7) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,i6,i7) )
      return m_map.m_impl_handle[ m_map.m_impl_offset(i0,i1,i2,i3,i4,i5,i6,i7) ];
    }

  template< typename I0 , typename I1 , typename I2 , typename I3
          , typename I4 , typename I5 , typename I6 , typename I7>
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<
    ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,I6,I7>::value
      && ( 8 == Rank )
      && ! is_default_map
    ), reference_type >::type
  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
            , const I4 & i4 , const I5 & i5 , const I6 & i6 , const I7 & i7 ) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,i6,i7) )
      return m_map.reference(i0,i1,i2,i3,i4,i5,i6,i7);
    }

#endif
  template< class ... Args >
  KOKKOS_FORCEINLINE_FUNCTION
  typename std::enable_if<( Kokkos::Impl::are_integral<Args...>::value
                            && ( 0 == Rank )
                          ), reference_type >::type
  access( Args ... args ) const
    {
      KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,args...) )
      return m_map.reference();
    }

   template< typename I0
               , class ... Args>
    KOKKOS_FORCEINLINE_FUNCTION
    typename std::enable_if<
      ( Kokkos::Impl::are_integral<I0,Args...>::value
        && ( 1 == Rank )
        && ! is_default_map
      ), reference_type >::type
    access( const I0 & i0,
                Args ... args) const
      {
        KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,args...) )
        return m_map.reference(i0);
      }

   template< typename I0
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,Args...>::value
       && ( 1 == Rank )
       && is_default_map
       && ! is_layout_stride
     ), reference_type >::type
   access( const I0 & i0
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,args...) )
       return m_map.m_impl_handle[ i0 ];
     }

   template< typename I0
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,Args...>::value
       && ( 1 == Rank )
       && is_default_map
       && is_layout_stride
     ), reference_type >::type
   access( const I0 & i0
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,args...) )
       return m_map.m_impl_handle[ m_map.m_impl_offset.m_stride.S0 * i0 ];
     }

   template< typename I0 , typename I1
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,Args...>::value
       && ( 2 == Rank )
       && ! is_default_map
     ), reference_type >::type
   access( const I0 & i0 , const I1 & i1
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,args...) )
       return m_map.reference(i0,i1);
     }

   template< typename I0 , typename I1
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,Args...>::value
       && ( 2 == Rank )
       && is_default_map
       && is_layout_left && ( traits::rank_dynamic == 0 )
     ), reference_type >::type
   access( const I0 & i0 , const I1 & i1
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,args...) )
       return m_map.m_impl_handle[ i0 + m_map.m_impl_offset.m_dim.N0 * i1 ];
     }

   template< typename I0 , typename I1
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,Args...>::value
       && ( 2 == Rank )
       && is_default_map
       && is_layout_left && ( traits::rank_dynamic != 0 )
     ), reference_type >::type
   access( const I0 & i0 , const I1 & i1
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,args...) )
       return m_map.m_impl_handle[ i0 + m_map.m_impl_offset.m_stride * i1 ];
     }

   template< typename I0 , typename I1
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,Args...>::value
       && ( 2 == Rank )
       && is_default_map
       && is_layout_right && ( traits::rank_dynamic == 0 )
     ), reference_type >::type
   access( const I0 & i0 , const I1 & i1
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,args...) )
       return m_map.m_impl_handle[ i1 + m_map.m_impl_offset.m_dim.N1 * i0 ];
     }

   template< typename I0 , typename I1
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,Args...>::value
       && ( 2 == Rank )
       && is_default_map
       && is_layout_right && ( traits::rank_dynamic != 0 )
     ), reference_type >::type
   access( const I0 & i0 , const I1 & i1
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,args...) )
       return m_map.m_impl_handle[ i1 + m_map.m_impl_offset.m_stride * i0 ];
     }

   template< typename I0 , typename I1
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,Args...>::value
       && ( 2 == Rank )
       && is_default_map
       && is_layout_stride
     ), reference_type >::type
   access( const I0 & i0 , const I1 & i1
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,args...) )
       return m_map.m_impl_handle[ i0 * m_map.m_impl_offset.m_stride.S0 +
                              i1 * m_map.m_impl_offset.m_stride.S1 ];
     }

   //------------------------------
   // Rank 3

   template< typename I0 , typename I1 , typename I2
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,Args...>::value
       && ( 3 == Rank )
       && is_default_map
     ), reference_type >::type
   access( const I0 & i0 , const I1 & i1 , const I2 & i2
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,args...) )
       return m_map.m_impl_handle[ m_map.m_impl_offset(i0,i1,i2) ];
     }

   template< typename I0 , typename I1 , typename I2
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,Args...>::value
       && ( 3 == Rank )
       && ! is_default_map
     ), reference_type >::type
   access( const I0 & i0 , const I1 & i1 , const I2 & i2
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,args...) )
       return m_map.reference(i0,i1,i2);
     }

   //------------------------------
   // Rank 4

   template< typename I0 , typename I1 , typename I2 , typename I3
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,I3,Args...>::value
       && ( 4 == Rank )
       && is_default_map
     ), reference_type >::type
   access( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,args...) )
       return m_map.m_impl_handle[ m_map.m_impl_offset(i0,i1,i2,i3) ];
     }

   template< typename I0 , typename I1 , typename I2 , typename I3
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,I3,Args...>::value
       && ( 4 == Rank )
       && ! is_default_map
     ), reference_type >::type
   access( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,args...) )
       return m_map.reference(i0,i1,i2,i3);
     }

   //------------------------------
   // Rank 5

   template< typename I0 , typename I1 , typename I2 , typename I3
           , typename I4
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,Args...>::value
       && ( 5 == Rank )
       && is_default_map
     ), reference_type >::type
   access( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
             , const I4 & i4
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,args...) )
       return m_map.m_impl_handle[ m_map.m_impl_offset(i0,i1,i2,i3,i4) ];
     }

   template< typename I0 , typename I1 , typename I2 , typename I3
           , typename I4
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,Args...>::value
       && ( 5 == Rank )
       && ! is_default_map
     ), reference_type >::type
   access( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
             , const I4 & i4
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,args...) )
       return m_map.reference(i0,i1,i2,i3,i4);
     }

   //------------------------------
   // Rank 6

   template< typename I0 , typename I1 , typename I2 , typename I3
           , typename I4 , typename I5
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,Args...>::value
       && ( 6 == Rank )
       && is_default_map
     ), reference_type >::type
   access( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
             , const I4 & i4 , const I5 & i5
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,args...) )
       return m_map.m_impl_handle[ m_map.m_impl_offset(i0,i1,i2,i3,i4,i5) ];
     }

   template< typename I0 , typename I1 , typename I2 , typename I3
           , typename I4 , typename I5
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,Args...>::value
       && ( 6 == Rank )
       && ! is_default_map
     ), reference_type >::type
   access( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
             , const I4 & i4 , const I5 & i5
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,args...) )
       return m_map.reference(i0,i1,i2,i3,i4,i5);
     }

   //------------------------------
   // Rank 7

   template< typename I0 , typename I1 , typename I2 , typename I3
           , typename I4 , typename I5 , typename I6
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,I6,Args...>::value
       && ( 7 == Rank )
       && is_default_map
     ), reference_type >::type
   access( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
             , const I4 & i4 , const I5 & i5 , const I6 & i6
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,i6,args...) )
       return m_map.m_impl_handle[ m_map.m_impl_offset(i0,i1,i2,i3,i4,i5,i6) ];
     }

   template< typename I0 , typename I1 , typename I2 , typename I3
           , typename I4 , typename I5 , typename I6
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,I6,Args...>::value
       && ( 7 == Rank )
       && ! is_default_map
     ), reference_type >::type
   access( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
             , const I4 & i4 , const I5 & i5 , const I6 & i6
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,i6,args...) )
       return m_map.reference(i0,i1,i2,i3,i4,i5,i6);
     }

   //------------------------------
   // Rank 8

   template< typename I0 , typename I1 , typename I2 , typename I3
           , typename I4 , typename I5 , typename I6 , typename I7
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,I6,I7,Args...>::value
       && ( 8 == Rank )
       && is_default_map
     ), reference_type >::type
   access( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
             , const I4 & i4 , const I5 & i5 , const I6 & i6 , const I7 & i7
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,i6,i7,args...) )
       return m_map.m_impl_handle[ m_map.m_impl_offset(i0,i1,i2,i3,i4,i5,i6,i7) ];
     }

   template< typename I0 , typename I1 , typename I2 , typename I3
           , typename I4 , typename I5 , typename I6 , typename I7
           , class ... Args >
   KOKKOS_FORCEINLINE_FUNCTION
   typename std::enable_if<
     ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,I6,I7,Args...>::value
       && ( 8 == Rank )
       && ! is_default_map
     ), reference_type >::type
   access( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
             , const I4 & i4 , const I5 & i5 , const I6 & i6 , const I7 & i7
             , Args ... args ) const
     {
       KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,i6,i7,args...) )
       return m_map.reference(i0,i1,i2,i3,i4,i5,i6,i7);
     }


#undef KOKKOS_IMPL_VIEW_OPERATOR_VERIFY

  //----------------------------------------
  // Standard destructor, constructors, and assignment operators

  KOKKOS_INLINE_FUNCTION
  ~View() {}

  KOKKOS_INLINE_FUNCTION
  View() : m_track(), m_map() {}

  KOKKOS_INLINE_FUNCTION
  View( const View & rhs ) : m_track( rhs.m_track, traits::is_managed ), m_map( rhs.m_map ) {}

  KOKKOS_INLINE_FUNCTION
  View( View && rhs ) : m_track( std::move(rhs.m_track) ), m_map( std::move(rhs.m_map) ) {}

  KOKKOS_INLINE_FUNCTION
  View & operator = ( const View & rhs ) { m_track = rhs.m_track ; m_map = rhs.m_map ; return *this ; }

  KOKKOS_INLINE_FUNCTION
  View & operator = ( View && rhs ) { m_track = std::move(rhs.m_track) ; m_map = std::move(rhs.m_map) ; return *this ; }



  //----------------------------------------
  // Compatible view copy constructor and assignment
  // may assign unmanaged from managed.

  template< class RT , class ... RP >
  KOKKOS_INLINE_FUNCTION
  View( const View<RT,RP...> & rhs,
        typename std::enable_if<Kokkos::Impl::ViewMapping<
        traits , typename View<RT,RP...>::traits , typename traits::specialize >::is_assignable_data_type>::type* = 0
     )
    : m_track( rhs.m_track , traits::is_managed )
    , m_map()
    {
      typedef typename View<RT,RP...>::traits  SrcTraits ;
      typedef Kokkos::Impl::ViewMapping< traits , SrcTraits , typename traits::specialize >  Mapping ;
      static_assert( Mapping::is_assignable , "Incompatible View copy construction" );
      Mapping::assign( m_map , rhs.m_map , rhs.m_track );
    }

  template< class RT , class ... RP >
  KOKKOS_INLINE_FUNCTION
  typename std::enable_if<Kokkos::Impl::ViewMapping<
     traits , typename View<RT,RP...>::traits , typename traits::specialize >::is_assignable_data_type,
     View>::type & operator = ( const View<RT,RP...> & rhs )
    {
      typedef typename View<RT,RP...>::traits  SrcTraits ;
      typedef Kokkos::Impl::ViewMapping< traits , SrcTraits , typename traits::specialize >  Mapping ;
      static_assert( Mapping::is_assignable , "Incompatible View copy assignment" );
      Mapping::assign( m_map , rhs.m_map , rhs.m_track );
      m_track.assign( rhs.m_track , traits::is_managed );
      return *this ;
    }

  //----------------------------------------
  // Compatible subview constructor
  // may assign unmanaged from managed.

  template< class RT , class ... RP , class Arg0 , class ... Args >
  KOKKOS_INLINE_FUNCTION
  View( const View< RT , RP... > & src_view
      , const Arg0 arg0 , Args ... args )
    : m_track( src_view.m_track , traits::is_managed )
    , m_map()
    {
      typedef View< RT , RP... > SrcType ;

      typedef Kokkos::Impl::ViewMapping
        < void /* deduce destination view type from source view traits */
        , typename SrcType::traits
        , Arg0 , Args... > Mapping ;

      typedef typename Mapping::type DstType ;

      static_assert( Kokkos::Impl::ViewMapping< traits , typename DstType::traits , typename traits::specialize >::is_assignable
        , "Subview construction requires compatible view and subview arguments" );

      Mapping::assign( m_map, src_view.m_map, arg0 , args... );
    }

  //----------------------------------------
  // Allocation tracking properties

  KOKKOS_INLINE_FUNCTION
  int use_count() const
    { return m_track.use_count(); }

  inline
  const std::string label() const
    { return m_track.template get_label< typename traits::memory_space >(); }

  //----------------------------------------
  // Allocation according to allocation properties and array layout

  template< class ... P >
  explicit inline
  View( const Impl::ViewCtorProp< P ... > & arg_prop
      , typename std::enable_if< ! Impl::ViewCtorProp< P... >::has_pointer
                               , typename traits::array_layout
                               >::type const & arg_layout
      )
    : m_track()
    , m_map()
    {
      // Append layout and spaces if not input
      typedef Impl::ViewCtorProp< P ... > alloc_prop_input ;

      // use 'std::integral_constant<unsigned,I>' for non-types
      // to avoid duplicate class error.
      typedef Impl::ViewCtorProp
        < P ...
        , typename std::conditional
            < alloc_prop_input::has_label
            , std::integral_constant<unsigned,0>
            , typename std::string
            >::type
        , typename std::conditional
            < alloc_prop_input::has_memory_space
            , std::integral_constant<unsigned,1>
            , typename traits::device_type::memory_space
            >::type
        , typename std::conditional
            < alloc_prop_input::has_execution_space
            , std::integral_constant<unsigned,2>
            , typename traits::device_type::execution_space
            >::type
        > alloc_prop ;

      static_assert( traits::is_managed
                   , "View allocation constructor requires managed memory" );

      if ( alloc_prop::initialize &&
#ifdef KOKKOS_ENABLE_DEPRECATED_CODE
           ! alloc_prop::execution_space::is_initialized()
#else
           ! alloc_prop::execution_space::impl_is_initialized()
#endif
           ) {
        // If initializing view data then
        // the execution space must be initialized.
        Kokkos::Impl::throw_runtime_exception("Constructing View and initializing data with uninitialized execution space");
      }

      // Copy the input allocation properties with possibly defaulted properties
      alloc_prop prop_copy( arg_prop );

//------------------------------------------------------------
#if defined( KOKKOS_ENABLE_CUDA )
      // If allocating in CudaUVMSpace must fence before and after
      // the allocation to protect against possible concurrent access
      // on the CPU and the GPU.
      // Fence using the trait's executon space (which will be Kokkos::Cuda)
      // to avoid incomplete type errors from usng Kokkos::Cuda directly.
      if ( std::is_same< Kokkos::CudaUVMSpace , typename traits::device_type::memory_space >::value ) {
        typename traits::device_type::memory_space::execution_space().fence();
      }
#endif
//------------------------------------------------------------

      Kokkos::Impl::SharedAllocationRecord<> *
        record = m_map.allocate_shared( prop_copy , arg_layout );

//------------------------------------------------------------
#if defined( KOKKOS_ENABLE_CUDA )
      if ( std::is_same< Kokkos::CudaUVMSpace , typename traits::device_type::memory_space >::value ) {
        typename traits::device_type::memory_space::execution_space().fence();
      }
#endif
//------------------------------------------------------------

      // Setup and initialization complete, start tracking
      m_track.assign_allocated_record_to_uninitialized( record );
    }

  KOKKOS_INLINE_FUNCTION
  void assign_data( pointer_type arg_data )
    {
      m_track.clear();
      m_map.assign_data( arg_data );
    }

  // Wrap memory according to properties and array layout
  template< class ... P >
  explicit KOKKOS_INLINE_FUNCTION
  View( const Impl::ViewCtorProp< P ... > & arg_prop
      , typename std::enable_if< Impl::ViewCtorProp< P... >::has_pointer
                               , typename traits::array_layout
                               >::type const & arg_layout
      )
    : m_track() // No memory tracking
    , m_map( arg_prop , arg_layout )
    {
      static_assert(
        std::is_same< pointer_type
                    , typename Impl::ViewCtorProp< P... >::pointer_type
                    >::value ,
        "Constructing View to wrap user memory must supply matching pointer type" );
    }

  // Simple dimension-only layout
  template< class ... P >
  explicit inline
  View( const Impl::ViewCtorProp< P ... > & arg_prop
      , typename std::enable_if< ! Impl::ViewCtorProp< P... >::has_pointer
                               , size_t
                               >::type const arg_N0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      )
    : View( arg_prop
          , typename traits::array_layout
              ( arg_N0 , arg_N1 , arg_N2 , arg_N3
              , arg_N4 , arg_N5 , arg_N6 , arg_N7 )
          )
    {
#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
    Impl::runtime_check_rank_host(traits::rank_dynamic, std::is_same<typename traits::specialize,void>::value, arg_N0, arg_N1, arg_N2, arg_N3,
                             arg_N4, arg_N5, arg_N6, arg_N7, label());
#else
    Impl::runtime_check_rank_device(traits::rank_dynamic, std::is_same<typename traits::specialize,void>::value, arg_N0, arg_N1, arg_N2, arg_N3,
                             arg_N4, arg_N5, arg_N6, arg_N7);

#endif

    }

  template< class ... P >
  explicit KOKKOS_INLINE_FUNCTION
  View( const Impl::ViewCtorProp< P ... > & arg_prop
      , typename std::enable_if< Impl::ViewCtorProp< P... >::has_pointer
                               , size_t
                               >::type const arg_N0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      )
    : View( arg_prop
          , typename traits::array_layout
              ( arg_N0 , arg_N1 , arg_N2 , arg_N3
              , arg_N4 , arg_N5 , arg_N6 , arg_N7 )
          )
    {
#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
    Impl::runtime_check_rank_host(traits::rank_dynamic, std::is_same<typename traits::specialize,void>::value, arg_N0, arg_N1, arg_N2, arg_N3,
                             arg_N4, arg_N5, arg_N6, arg_N7, label());
#else
    Impl::runtime_check_rank_device(traits::rank_dynamic, std::is_same<typename traits::specialize,void>::value, arg_N0, arg_N1, arg_N2, arg_N3,
                             arg_N4, arg_N5, arg_N6, arg_N7);

#endif

    }

  // Allocate with label and layout
  template< typename Label >
  explicit inline
  View( const Label & arg_label
      , typename std::enable_if<
          Kokkos::Impl::is_view_label<Label>::value ,
          typename traits::array_layout >::type const & arg_layout
      )
    : View( Impl::ViewCtorProp< std::string >( arg_label ) , arg_layout )
    {}

  // Allocate label and layout, must disambiguate from subview constructor.
  template< typename Label >
  explicit inline
  View( const Label & arg_label
      , typename std::enable_if<
          Kokkos::Impl::is_view_label<Label>::value ,
        const size_t >::type arg_N0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      )
    : View( Impl::ViewCtorProp< std::string >( arg_label )
          , typename traits::array_layout
              ( arg_N0 , arg_N1 , arg_N2 , arg_N3
              , arg_N4 , arg_N5 , arg_N6 , arg_N7 )
          )
    {
      static_assert ( traits::array_layout::is_extent_constructible , "Layout is not extent constructible. A layout object should be passed too.\n" );
	  
#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
    Impl::runtime_check_rank_host(traits::rank_dynamic, std::is_same<typename traits::specialize,void>::value, arg_N0, arg_N1, arg_N2, arg_N3,
                             arg_N4, arg_N5, arg_N6, arg_N7, label());
#else
    Impl::runtime_check_rank_device(traits::rank_dynamic, std::is_same<typename traits::specialize,void>::value, arg_N0, arg_N1, arg_N2, arg_N3,
                             arg_N4, arg_N5, arg_N6, arg_N7);

#endif



    }

  // For backward compatibility
  explicit inline
  View( const ViewAllocateWithoutInitializing & arg_prop
      , const typename traits::array_layout & arg_layout
      )
    : View( Impl::ViewCtorProp< std::string , Kokkos::Impl::WithoutInitializing_t >( arg_prop.label , Kokkos::WithoutInitializing )
          , arg_layout
          )
    {}

  explicit inline
  View( const ViewAllocateWithoutInitializing & arg_prop
      , const size_t arg_N0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      )
    : View( Impl::ViewCtorProp< std::string , Kokkos::Impl::WithoutInitializing_t >( arg_prop.label , Kokkos::WithoutInitializing )
          , typename traits::array_layout
              ( arg_N0 , arg_N1 , arg_N2 , arg_N3
              , arg_N4 , arg_N5 , arg_N6 , arg_N7 )
          )
    {
#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
    Impl::runtime_check_rank_host(traits::rank_dynamic, std::is_same<typename traits::specialize,void>::value, arg_N0, arg_N1, arg_N2, arg_N3,
                             arg_N4, arg_N5, arg_N6, arg_N7, label());
#else
    Impl::runtime_check_rank_device(traits::rank_dynamic, std::is_same<typename traits::specialize,void>::value, arg_N0, arg_N1, arg_N2, arg_N3,
                             arg_N4, arg_N5, arg_N6, arg_N7);

#endif

    }
  template <class Traits>
  KOKKOS_INLINE_FUNCTION
  View( const track_type & track,  const Kokkos::Impl::ViewMapping< Traits , typename Traits::specialize >  &map ) :
  m_track(track), m_map()
  {
    typedef Kokkos::Impl::ViewMapping< traits , Traits , typename traits::specialize >  Mapping ;
    static_assert( Mapping::is_assignable , "Incompatible View copy construction" );
    Mapping::assign( m_map , map , track );
  }

  //----------------------------------------
  // Memory span required to wrap these dimensions.
  static constexpr size_t required_allocation_size(
                                       const size_t arg_N0 = 0
                                     , const size_t arg_N1 = 0
                                     , const size_t arg_N2 = 0
                                     , const size_t arg_N3 = 0
                                     , const size_t arg_N4 = 0
                                     , const size_t arg_N5 = 0
                                     , const size_t arg_N6 = 0
                                     , const size_t arg_N7 = 0
                                     )
    {
      return map_type::memory_span(
        typename traits::array_layout
          ( arg_N0 , arg_N1 , arg_N2 , arg_N3
          , arg_N4 , arg_N5 , arg_N6 , arg_N7 ) );
    }

  explicit KOKKOS_INLINE_FUNCTION
  View( pointer_type arg_ptr
      , const size_t arg_N0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      )
    : View( Impl::ViewCtorProp<pointer_type>(arg_ptr)
          , typename traits::array_layout
             ( arg_N0 , arg_N1 , arg_N2 , arg_N3
             , arg_N4 , arg_N5 , arg_N6 , arg_N7 )
          )
    {
#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
    Impl::runtime_check_rank_host(traits::rank_dynamic, std::is_same<typename traits::specialize,void>::value, arg_N0, arg_N1, arg_N2, arg_N3,
                             arg_N4, arg_N5, arg_N6, arg_N7, label());
#else
    Impl::runtime_check_rank_device(traits::rank_dynamic, std::is_same<typename traits::specialize,void>::value, arg_N0, arg_N1, arg_N2, arg_N3,
                             arg_N4, arg_N5, arg_N6, arg_N7);

#endif
    }

  explicit KOKKOS_INLINE_FUNCTION
  View( pointer_type arg_ptr
      , const typename traits::array_layout & arg_layout
      )
    : View( Impl::ViewCtorProp<pointer_type>(arg_ptr) , arg_layout )
    {

    }

  //----------------------------------------
  // Shared scratch memory constructor

  static inline
  size_t
  shmem_size( const size_t arg_N0 = KOKKOS_INVALID_INDEX,
              const size_t arg_N1 = KOKKOS_INVALID_INDEX,
              const size_t arg_N2 = KOKKOS_INVALID_INDEX,
              const size_t arg_N3 = KOKKOS_INVALID_INDEX,
              const size_t arg_N4 = KOKKOS_INVALID_INDEX,
              const size_t arg_N5 = KOKKOS_INVALID_INDEX,
              const size_t arg_N6 = KOKKOS_INVALID_INDEX,
              const size_t arg_N7 = KOKKOS_INVALID_INDEX )
  {
    if ( is_layout_stride ) {
      Kokkos::abort( "Kokkos::View::shmem_size(extents...) doesn't work with LayoutStride. Pass a LayoutStride object instead" );
    }
    const size_t num_passed_args = Impl::count_valid_integers(arg_N0, arg_N1, arg_N2, arg_N3,
                                                              arg_N4, arg_N5, arg_N6, arg_N7);

    if ( std::is_same<typename traits::specialize,void>::value && num_passed_args != traits::rank_dynamic ) {
      Kokkos::abort( "Kokkos::View::shmem_size() rank_dynamic != number of arguments.\n" );
    }

    return View::shmem_size(
           typename traits::array_layout
            ( arg_N0 , arg_N1 , arg_N2 , arg_N3
            , arg_N4 , arg_N5 , arg_N6 , arg_N7 ) );
  }

  static inline
  size_t shmem_size( typename traits::array_layout const& arg_layout )
  {
    return map_type::memory_span( arg_layout )+sizeof(typename traits::value_type);
  }

  explicit KOKKOS_INLINE_FUNCTION
  View( const typename traits::execution_space::scratch_memory_space & arg_space
      , const typename traits::array_layout & arg_layout )
    : View( Impl::ViewCtorProp<pointer_type>(
              reinterpret_cast<pointer_type>(
                arg_space.get_shmem_aligned( map_type::memory_span( arg_layout ), sizeof(typename traits::value_type) ) ) )
         , arg_layout )
    {}

  explicit KOKKOS_INLINE_FUNCTION
  View( const typename traits::execution_space::scratch_memory_space & arg_space
      , const size_t arg_N0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG
      , const size_t arg_N7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG )
    : View( Impl::ViewCtorProp<pointer_type>(
              reinterpret_cast<pointer_type>(
                arg_space.get_shmem_aligned(
                  map_type::memory_span(
                    typename traits::array_layout
                     ( arg_N0 , arg_N1 , arg_N2 , arg_N3
                     , arg_N4 , arg_N5 , arg_N6 , arg_N7 ) ), sizeof(typename traits::value_type) ) ) )
          , typename traits::array_layout
             ( arg_N0 , arg_N1 , arg_N2 , arg_N3
             , arg_N4 , arg_N5 , arg_N6 , arg_N7 )
       )
    {

#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
    Impl::runtime_check_rank_host(traits::rank_dynamic, std::is_same<typename traits::specialize,void>::value, arg_N0, arg_N1, arg_N2, arg_N3,
                             arg_N4, arg_N5, arg_N6, arg_N7, label());
#else
    Impl::runtime_check_rank_device(traits::rank_dynamic, std::is_same<typename traits::specialize,void>::value, arg_N0, arg_N1, arg_N2, arg_N3,
                             arg_N4, arg_N5, arg_N6, arg_N7);

#endif
    }
};


 /** \brief Temporary free function rank()
  *         until rank() is implemented
  *         in the View
  */
  template < typename D , class ... P >
  KOKKOS_INLINE_FUNCTION
  constexpr unsigned rank( const View<D , P...> & V ) { return V.Rank; } //Temporary until added to view

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

template< class V , class ... Args >
using Subview =
  typename Kokkos::Impl::ViewMapping
    < void /* deduce subview type from source view traits */
    , typename V::traits
    , Args ...
    >::type ;

template< class D, class ... P , class ... Args >
KOKKOS_INLINE_FUNCTION
typename Kokkos::Impl::ViewMapping
  < void /* deduce subview type from source view traits */
  , ViewTraits< D , P... >
  , Args ...
  >::type
subview( const View< D, P... > & src , Args ... args )
{
  static_assert( View< D , P... >::Rank == sizeof...(Args) ,
    "subview requires one argument for each source View rank" );

  return typename
    Kokkos::Impl::ViewMapping
      < void /* deduce subview type from source view traits */
      , ViewTraits< D , P ... >
      , Args ... >::type( src , args ... );
}

template< class MemoryTraits , class D, class ... P , class ... Args >
KOKKOS_INLINE_FUNCTION
typename Kokkos::Impl::ViewMapping
  < void /* deduce subview type from source view traits */
  , ViewTraits< D , P... >
  , Args ...
  >::template apply< MemoryTraits >::type
subview( const View< D, P... > & src , Args ... args )
{
  static_assert( View< D , P... >::Rank == sizeof...(Args) ,
    "subview requires one argument for each source View rank" );

  return typename
    Kokkos::Impl::ViewMapping
      < void /* deduce subview type from source view traits */
      , ViewTraits< D , P ... >
      , Args ... >
      ::template apply< MemoryTraits >
      ::type( src , args ... );
}

} /* namespace Kokkos */

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

namespace Kokkos {

template< class LT , class ... LP , class RT , class ... RP >
KOKKOS_INLINE_FUNCTION
bool operator == ( const View<LT,LP...> & lhs ,
                   const View<RT,RP...> & rhs )
{
  // Same data, layout, dimensions
  typedef ViewTraits<LT,LP...>  lhs_traits ;
  typedef ViewTraits<RT,RP...>  rhs_traits ;

  return
    std::is_same< typename lhs_traits::const_value_type ,
                  typename rhs_traits::const_value_type >::value &&
    std::is_same< typename lhs_traits::array_layout ,
                  typename rhs_traits::array_layout >::value &&
    std::is_same< typename lhs_traits::memory_space ,
                  typename rhs_traits::memory_space >::value &&
    unsigned(lhs_traits::rank) == unsigned(rhs_traits::rank) &&
    lhs.data()        == rhs.data() &&
    lhs.span()        == rhs.span() &&
    lhs.extent(0) == rhs.extent(0) &&
    lhs.extent(1) == rhs.extent(1) &&
    lhs.extent(2) == rhs.extent(2) &&
    lhs.extent(3) == rhs.extent(3) &&
    lhs.extent(4) == rhs.extent(4) &&
    lhs.extent(5) == rhs.extent(5) &&
    lhs.extent(6) == rhs.extent(6) &&
    lhs.extent(7) == rhs.extent(7);
}

template< class LT , class ... LP , class RT , class ... RP >
KOKKOS_INLINE_FUNCTION
bool operator != ( const View<LT,LP...> & lhs ,
                   const View<RT,RP...> & rhs )
{
  return ! ( operator==(lhs,rhs) );
}

} /* namespace Kokkos */

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

namespace Kokkos {
namespace Impl {

inline
void shared_allocation_tracking_disable()
{ Kokkos::Impl::SharedAllocationRecord<void,void>::tracking_disable(); }

inline
void shared_allocation_tracking_enable()
{ Kokkos::Impl::SharedAllocationRecord<void,void>::tracking_enable(); }

} /* namespace Impl */
} /* namespace Kokkos */

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

namespace Kokkos { namespace Impl {

template < class Specialize, typename A, typename B >
struct CommonViewValueType;

template < typename A, typename B >
struct CommonViewValueType< void, A, B >
{
  using value_type = typename std::common_type< A , B >::type;
};


template < class Specialize, class ValueType >
struct CommonViewAllocProp;

template < class ValueType >
struct CommonViewAllocProp< void, ValueType >
{
  using value_type = ValueType;
  using scalar_array_type = ValueType;

  template < class ... Views >
  KOKKOS_INLINE_FUNCTION
  CommonViewAllocProp( const Views & ... ) {}
};


template < class ... Views >
struct DeduceCommonViewAllocProp;

// Base case must provide types for:
// 1. specialize  2. value_type  3. is_view  4. prop_type
template < class FirstView >
struct DeduceCommonViewAllocProp< FirstView >
{
  using specialize = typename FirstView::traits::specialize;

  using value_type = typename FirstView::traits::value_type;

  enum : bool { is_view = is_view< FirstView >::value };

  using prop_type = CommonViewAllocProp< specialize, value_type >;
};


template < class FirstView, class ... NextViews >
struct DeduceCommonViewAllocProp< FirstView, NextViews... >
{
  using NextTraits = DeduceCommonViewAllocProp< NextViews... >;

  using first_specialize = typename FirstView::traits::specialize;
  using first_value_type = typename FirstView::traits::value_type;

  enum : bool { first_is_view = is_view< FirstView >::value };

  using next_specialize = typename NextTraits::specialize;
  using next_value_type = typename NextTraits::value_type;

  enum : bool { next_is_view = NextTraits::is_view };

  // common types

  // determine specialize type
  // if first and next specialize differ, but are not the same specialize, error out
  static_assert( !(!std::is_same< first_specialize, next_specialize >::value && !std::is_same< first_specialize, void>::value && !std::is_same< void, next_specialize >::value)  , "Kokkos DeduceCommonViewAllocProp ERROR: Only one non-void specialize trait allowed" );

  // otherwise choose non-void specialize if either/both are non-void
  using specialize = typename std::conditional< std::is_same< first_specialize, next_specialize >::value
                                              , first_specialize
                                              , typename std::conditional< ( std::is_same< first_specialize, void >::value
                                                                             && !std::is_same< next_specialize, void >::value)
                                                                           , next_specialize
                                                                           , first_specialize
                                                                         >::type
                                               >::type;

  using value_type = typename CommonViewValueType< specialize, first_value_type, next_value_type >::value_type;

  enum : bool { is_view = (first_is_view && next_is_view) };

  using prop_type = CommonViewAllocProp< specialize, value_type >;
};

} // end namespace Impl

template < class ... Views >
using DeducedCommonPropsType = typename Impl::DeduceCommonViewAllocProp<Views...>::prop_type ;

// User function
template < class ... Views >
KOKKOS_INLINE_FUNCTION
DeducedCommonPropsType<Views...> 
common_view_alloc_prop( Views const & ... views )
{
  return DeducedCommonPropsType<Views...>( views... );
}

} // namespace Kokkos


namespace Kokkos {
namespace Impl {

using Kokkos::is_view ;

} /* namespace Impl */
} /* namespace Kokkos */

#include <impl/Kokkos_ViewUniformType.hpp>
#include <impl/Kokkos_Atomic_View.hpp>

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

#endif /* #ifndef KOKKOS_VIEW_HPP */

